import json
import os
import pathlib
import shutil
import time
from service import projectService, processService

from entity.Project import Project
import utils.jsonData as JsonData

import requests

das_path = pathlib.Path(".").absolute()
project_dir_path = das_path / "project"


def check_and_extract_project(file, project_path="", tag=0):
    """检查、解压、保存项目, tag=0表示新项目、会在数据库中新增数据，tag=1表示已有项目，直接删除更新本地项目即可"""
    # 上传的文件名字
    filename = file.filename
    # 上传的文件路径
    file_path = das_path / "project" / filename
    # 即将生成的项目名
    project_name = filename.split(".")[0]
    # 即将生成的项目路径
    project_path_to_will = das_path / "project" / project_name

    file.save(file_path)
    while not file_path.is_file():
        time.sleep(0.1)

    # 如果project_path不为空，删除
    if project_path:
        remove_dir(project_path)
    # 解压、保存项目
    project_path, _res = extract_project(filename, project_name, project_path, tag)
    # 解压后删除压缩包
    if file_path.is_file():
        remove_file(file_path)
    # 如果project_path返回为False，删除上传的文件以及解压的项目，返回失败信息
    if not project_path:
        remove_dir(project_path_to_will)
        return False, _res

    # 检查文件配置文件是否合法
    return check_project(project_path, _res)


def extract_project(file_name, project_name, project_path_old, tag):
    """解压"""
    # 到project文件加的路径
    project_dir = das_path / "project"
    # 已保存的文件路径
    project_path = project_dir / project_name

    # 解压文件至project文件加下
    _res = os.system(f"7z.exe x -o"
                     f"{project_dir} "
                     f"{project_dir}/{file_name}"
                     )

    # 如果解压成功，保存持久化数据，否则返回错误信息
    if _res:
        os.remove(f"{project_dir}/{file_name}")
        return False, JsonData.JsonData().error("1006", "不是正确的打包文件！")
    while not project_path.is_dir():
        time.sleep(0.1)
    if tag:
        project_path.rename(project_path_old)
        return project_path_old, JsonData.JsonData().success("项目更新成功")
    return project_to_database(project_name, project_path)


def project_to_database(project_name, project_path):
    """保存项目信息至数据库"""
    _res = json.loads(projectService.create_project(project_name))
    # 如果插入失败返回信息
    if _res["code"] != "200":
        return False, _res
    # 插入成功重命名文件名
    project_id = str(_res["data"][0])
    # 重命名之前检查是否有重复的编号，如果有删除重复编号的文件夹
    remove_dir(pathlib.Path(str(project_path) + str(project_id)))
    # 重命名
    project_path = project_path.rename("project/" + project_name + project_id)
    return project_path, _res


def remove_dir(dir_path):
    """删除文件夹以及其中所有文件"""
    dir_path = pathlib.Path(dir_path)
    if dir_path.is_dir():
        shutil.rmtree(dir_path)


def remove_file(file_path):
    """删除文件"""
    file_path = pathlib.Path(file_path)
    if file_path.is_file():
        os.remove(file_path)


def get_scene(project):
    """获取场景的列表"""
    _list = []
    for i in project.project.rglob("*"):
        if i.is_dir():
            _list.append(i)
    return _list


def check_project(project_path, res):
    """检查项目是否符合配置要求"""
    project_path = pathlib.Path(project_path)
    project = Project(project_path, project_path / "app.dsft.ini")
    project.config.read_config()
    if len(project.config.run_order) == len(get_scene(project)):
        for i in project.config.run_order:
            for j in i["jump"]:
                if i["jump"][j] == "正常终止":
                    return res
    return JsonData.JsonData().error("配置信息错误，请用ddt工具尝试运行")


def remove_project_file(project):
    """根据project对象删除对应的本地文件"""
    if project.project.is_dir():
        shutil.rmtree(project)


def project_to_package(project_file_path, project_id):
    """打包输入的文件夹"""
    if not project_file_path.is_dir():
        return False, JsonData.JsonData().error("1007", f"下载失败，服务端不存在该项目缓存，建议删除表数据！")
    _res = os.system(f"7z.exe a "
                     f"{project_dir_path/str(project_id)}.dsft.ini "
                     f"{project_file_path} "
                     f"-mx9")
    if _res == 0:
        return True, f"{project_dir_path/str(project_id)}.dsft.ini"
    return False, JsonData.JsonData().error("1007", f"下载失败，服务端项目打包失败")